package com.abel.bigwater.data.sanchuan

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.data.NotEnoughDataException
import com.fasterxml.jackson.databind.ObjectMapper
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageDecoder
import org.slf4j.LoggerFactory

open class SanchuanDecoder : ByteToMessageDecoder() {
    /**
     * Decode the from one [ByteBuf] to an other. This method will be called till either the input
     * [ByteBuf] has nothing to read when return from this method or till nothing was read from the input
     * [ByteBuf].
     *
     * @param ctx           the [ChannelHandlerContext] which this [ByteToMessageDecoder] belongs to
     * @param in            the [ByteBuf] from which to read data
     * @param out           the [List] to which decoded messages should be added
     * @throws Exception    is thrown if an error occurs
     */
    override fun decode(ctx: ChannelHandlerContext?, `in`: ByteBuf?, out: MutableList<Any>?) {
        `in` ?: return
        lgr.info("收到消息:\n${BcdString.create(`in`.duplicate(), `in`.readableBytes()).bcdStringBlank()}")
        if (`in`.readableBytes() < SanchuanPacket.MIN_LEN) return

        while (`in`.readableBytes() > 0) {
            try {
                val p1 = SanchuanPacket.parseBuffer(`in`)

                if (p1 != null) out!!.add(p1)
            } catch (ex: NotEnoughDataException) {
                break
            }
        }

        lgr.info("收到三川消息 ${out?.size} 条: ${ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(out)}")
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext?, cause: Throwable?) {
        lgr.error("连接${ctx?.channel()?.remoteAddress()}异常: ${cause?.message}")
        lgr.debug(cause?.message, cause)

        ctx?.close()
    }

    companion object {
        private val lgr = LoggerFactory.getLogger(SanchuanDecoder::class.java)
    }
}